import { ReactRenderer } from '@tiptap/react';
import tippy from 'tippy.js';
import { MaterialList } from './material-list';
import { getMaterialList } from './utils';
import type { Instance } from 'tippy.js';
import type { SuggestionProps } from '@tiptap/suggestion';
import type { MaterialOptions } from './material';
import type { IMaterialProps, IMaterialRecord, IMaterialRef, IRegisterProps } from './types';

export const register = ({ componentProps }: IRegisterProps) => {
  const suggestion: MaterialOptions<IMaterialRecord>['suggestion'] = {
    items: ({ query }) => {
      return getMaterialList().filter((item) => item.keywords.toLowerCase().startsWith(query.toLowerCase()));
    },

    render: () => {
      let component: ReactRenderer<IMaterialRef, IMaterialProps>;
      let popup: Instance[];
      let clientRect: SuggestionProps['clientRect'];

      const scrollHandler = () => {
        if (clientRect) popup[0].setProps({ getReferenceClientRect: clientRect as any });
      };

      return {
        onStart: (props) => {
          component = new ReactRenderer(MaterialList, { props: { ...props, ...componentProps }, editor: props.editor });

          if (!props.clientRect) return;

          clientRect = props.clientRect;
          popup = tippy('body', {
            getReferenceClientRect: props.clientRect as any,
            appendTo: () => document.body,
            content: component.element,
            showOnCreate: true,
            interactive: true,
            trigger: 'manual',
            placement: 'bottom-start',
            maxWidth: 'max-content',
            duration: 0,
          });
          props.editor.view.dom.addEventListener('scroll', scrollHandler);
        },

        onUpdate(props) {
          component.updateProps({ ...props, ...componentProps });
          if (!props.clientRect) return;
          clientRect = props.clientRect;
          popup[0].setProps({ getReferenceClientRect: props.clientRect as any });
        },

        onKeyDown(props) {
          if (props.event.key === 'Escape') {
            popup[0].hide();
            return true;
          }
          if (!component.ref) return true;

          return component.ref?.onKeyDown(props);
        },

        onExit({ editor }) {
          popup?.[0].destroy();
          component?.destroy();
          editor.view.dom.removeEventListener('scroll', scrollHandler);
        },
      };
    },
  };
  return suggestion;
};
